/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.view.main;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jfonia.commands.Command;
import org.jfonia.commands.CommandStack;
import org.jfonia.connect5.basics.BasicValueNode;
import org.jfonia.connect5.basics.MutableValueNode;
import org.jfonia.connect5.basics.Observer;
import org.jfonia.constants.ModelConstants;
import org.jfonia.model.ListObservable;
import org.jfonia.model.StaffCollection;
import org.jfonia.model.TempoMap;
import org.jfonia.model.TempoNode;
import org.jfonia.view.scribbles.Scribble;
import org.jfonia.view.scribbles.Scribbles;
import org.jfonia.view.labels.Label;
import org.jfonia.view.labels.Labels;
import percussiongenerator.model.TrackCollection;

/**
 * Groups the staffcollection objects
 * Notifies its observes when a staffcollection is added or removed
 *
 * @author Rik Bauwens
 */
public class LeadSheet extends ListObservable<StaffCollection> implements Iterable<StaffCollection>
{
        private int version;
        private String name;
        private String author;
        private String description;

        private CommandStack commandStack;
        private Labels labels;
        private Scribbles scribbles;

        private List<StaffCollection> staffCollections;
        private TempoMap tempoMap;
        private TempoNode tempoNode;
        private TrackCollection trackCollection;
        private MutableValueNode<String> instrumentNode;

        public LeadSheet()
        {
                version = ModelConstants.VERSION;
                commandStack = new CommandStack();
                labels = new Labels();
                scribbles = new Scribbles();
                staffCollections = new ArrayList<StaffCollection>();
                tempoMap = new TempoMap();
                tempoNode = new TempoNode();
                tempoMap.add(tempoNode);
                instrumentNode = new BasicValueNode<String>("");
                instrumentNode.addObserver(new Observer()
                {
                        public void onNotify(Object source)
                        {
                                LeadSheetPlayer.getInstance().setInstrument(instrumentNode.getValue());
                        }
                });
        }

        public int getVersion()
        {
                return version;
        }

        public String getName()
        {
                return name;
        }
        
        public void setName(String name)
        {
                this.name = name;
        }

        public String getAuthor()
        {
                return author;
        }

        public void setAuthor(String author)
        {
                this.author = author;
        }

        public String getDescription()
        {
                return description;
        }

        public void setDescription(String description)
        {
                this.description = description;
        }

        public void execute(Command command)
        {
                commandStack.executeCommand(command);
        }

        public boolean canUndo()
        {
                return commandStack.canUndo();
        }

        public boolean canRedo()
        {
                return commandStack.canRedo();
        }

        public void undo()
        {
                commandStack.undo();
        }

        public void redo()
        {
                commandStack.redo();
        }

        //Temporary?
        public CommandStack getCommandStack()
        {
                return commandStack;
        }

        public Labels getLabels()
        {
                return labels;
        }

        public void addLabel(Label label)
        {
                labels.addLabel(label);
        }

        public void removeLabel(Label label)
        {
                labels.removeLabel(label);
        }

        public Scribbles getScribbles()
        {
                return scribbles;
        }

        public void addScribble(Scribble scribble)
        {
                scribbles.addScribble(scribble);
        }

        public int getBPM()
        {
                return tempoNode.getBPM();
        }

        public String getInstrument()
        {
                return instrumentNode.getValue();
        }

        public LeadSheet setBPM(int bpm)
        {
                tempoNode.setBPM(bpm);
                return this;
        }

        public LeadSheet setInstrument(String instrument)
        {
                instrumentNode.setValue(instrument);
                return this;
        }

        public MutableValueNode<Integer> getBPMNode()
        {
                return tempoNode.getBPMNode();
        }

        public MutableValueNode<String> getInstrumentNode()
        {
                return instrumentNode;
        }

        public TempoMap getTempoMap()
        {
                return tempoMap;
        }

        public StaffCollection getStaffCollection()
        {
                return staffCollections.iterator().next();
        }

        public void addStaffCollection(StaffCollection staffCollection)
        {
                staffCollections.add(staffCollection);
                itemAdded(staffCollection);
        }

        public void removeStaffCollection(StaffCollection staffCollection)
        {
                staffCollections.remove(staffCollection);
                itemRemoved(staffCollection);
        }
        
        public TrackCollection getTrackCollection()
        {
                return trackCollection;
        }

        public Iterator<StaffCollection> iterator()
        {
                return staffCollections.iterator();
        }
}
